home *** CD-ROM | disk | FTP | other *** search
- #include <errno.h>
- #include <ctype.h>
- #include <varargs.h>
- #include <sys/ioctl.h>
-
- #include "scheme.h"
-
- extern int errno;
-
- int Saved_Errno;
-
- static Object V_Print_Depth, V_Print_Length;
-
- Init_Print () {
- Define_Variable (&V_Print_Depth, "print-depth",
- Make_Fixnum (DEF_PRINT_DEPTH));
- Define_Variable (&V_Print_Length, "print-length",
- Make_Fixnum (DEF_PRINT_LEN));
- }
-
- Print_Length () {
- Object pl;
-
- pl = Var_Get (V_Print_Length);
- return TYPE(pl) == T_Fixnum ? FIXNUM(pl) : DEF_PRINT_LEN;
- }
-
- Print_Depth () {
- Object pd;
-
- pd = Var_Get (V_Print_Depth);
- return TYPE(pd) == T_Fixnum ? FIXNUM(pd) : DEF_PRINT_DEPTH;
- }
-
- Print_Char (port, c) Object port; register c; {
- char buf[1];
-
- if (PORT(port)->flags & P_STRING) {
- buf[0] = c;
- Print_String (port, buf, 1);
- } else {
- if (putc (c, PORT(port)->file) == EOF) {
- Saved_Errno = errno; /* errno valid here? */
- Primitive_Error ("write error on ~s: ~E", port);
- }
- }
- }
-
- Print_String (port, buf, len) Object port; register char *buf; register len; {
- register n;
- register struct S_Port *p;
- Object new;
- GC_Node;
-
- p = PORT(port);
- n = STRING(p->name)->size - p->ptr;
- if (n < len) {
- GC_Link (port);
- n = len - n;
- if (n < STRING_GROW_SIZE)
- n = STRING_GROW_SIZE;
- new = Make_String ((char *)0, STRING(p->name)->size + n);
- p = PORT(port);
- GC_Unlink;
- bcopy (STRING(p->name)->data, STRING(new)->data, p->ptr);
- p->name = new;
- }
- bcopy (buf, STRING(p->name)->data + p->ptr, len);
- p->ptr += len;
- }
-
- #ifndef VPRINTF
- vfprintf (f, fmt, ap) register FILE *f; register char *fmt; va_list ap; {
- _doprnt (fmt, ap, f);
- }
-
- vsprintf (s, fmt, ap) register char *s, *fmt; va_list ap; {
- FILE x;
- x._flag = _IOWRT|_IOSTRG;
- x._ptr = s;
- x._cnt = 1024;
- _doprnt (fmt, ap, &x);
- putc ('\0', &x);
- }
- #endif
-
- /*VARARGS0*/
- Printf (va_alist) va_dcl {
- va_list args;
- Object port;
- char *fmt;
- char buf[1024];
-
- va_start (args);
- port = va_arg (args, Object);
- fmt = va_arg (args, char *);
- if (PORT(port)->flags & P_STRING) {
- vsprintf (buf, fmt, args);
- Print_String (port, buf, strlen (buf));
- } else {
- vfprintf (PORT(port)->file, fmt, args);
- if (ferror (PORT(port)->file)) {
- Saved_Errno = errno; /* errno valid here? */
- Primitive_Error ("write error on ~s: ~E", port);
- }
- }
- va_end (args);
- }
-
- Object General_Print (argc, argv, raw) Object *argv; {
- General_Print_Object (argv[0], argc == 2 ? argv[1] : Curr_Output_Port, raw);
- return Void;
- }
-
- Object P_Write (argc, argv) Object *argv; {
- return General_Print (argc, argv, 0);
- }
-
- Object P_Display (argc, argv) Object *argv; {
- return General_Print (argc, argv, 1);
- }
-
- Object P_Write_Char (argc, argv) Object *argv; {
- Check_Type (argv[0], T_Character);
- return General_Print (argc, argv, 1);
- }
-
- /*VARARGS1*/
- Object P_Newline (argc, argv) Object *argv; {
- General_Print_Object (Newline, argc == 1 ? argv[0] : Curr_Output_Port, 1);
- return Void;
- }
-
- Object P_Print (argc, argv) Object *argv; {
- Object port;
- GC_Node;
-
- port = argc == 2 ? argv[1] : Curr_Output_Port;
- GC_Link (port);
- General_Print_Object (argv[0], port, 0);
- Print_Char (port, '\n');
- Flush_Output (port);
- GC_Unlink;
- return Void;
- }
-
- Object P_Clear_Output_Port (argc, argv) Object *argv; {
- Discard_Output (argc == 1 ? argv[0] : Curr_Output_Port);
- return Void;
- }
-
- Discard_Output (port) Object port; {
- register FILE *f;
-
- Check_Output_Port (port);
- if (PORT(port)->flags & P_STRING)
- return;
- f = PORT(port)->file;
- f->_cnt = 0;
- f->_ptr = f->_base;
- #ifdef TIOCFLUSH
- (void)ioctl (fileno (f), TIOCFLUSH, (char *)0);
- #endif
- }
-
- Object P_Flush_Output_Port (argc, argv) Object *argv; {
- Flush_Output (argc == 1 ? argv[0] : Curr_Output_Port);
- return Void;
- }
-
- Flush_Output (port) Object port; {
- Check_Output_Port (port);
- if (PORT(port)->flags & P_STRING)
- return;
- if (fflush (PORT(port)->file) == EOF) {
- Saved_Errno = errno; /* errno valid here? */
- Primitive_Error ("write error on ~s: ~E", port);
- }
- }
-
- Object P_Get_Output_String (port) Object port; {
- register struct S_Port *p;
- Object str;
- GC_Node;
-
- Check_Output_Port (port);
- GC_Link (port);
- str = Make_String ((char *)0, PORT(port)->ptr);
- p = PORT(port);
- bcopy (STRING(p->name)->data, STRING(str)->data, p->ptr);
- p->ptr = 0;
- GC_Unlink;
- return str;
- }
-
- Check_Output_Port (port) Object port; {
- Check_Type (port, T_Port);
- if (!(PORT(port)->flags & P_OPEN))
- Primitive_Error ("port has been closed: ~s", port);
- if (!IS_OUTPUT(port))
- Primitive_Error ("not an output port: ~s", port);
- }
-
- General_Print_Object (x, port, raw) Object x, port; {
- Check_Output_Port (port);
- Print_Object (x, port, raw, Print_Depth (), Print_Length ());
- }
-
- Print_Object (x, port, raw, depth, length) Object x, port;
- register raw, depth, length; {
- register t;
- GC_Node2;
-
- GC_Link2 (port, x);
- t = TYPE(x);
- switch (t) {
- case T_Null:
- Printf (port, "()");
- break;
- case T_Fixnum:
- Printf (port, "%d", FIXNUM(x));
- break;
- case T_Bignum:
- Print_Bignum (port, x);
- break;
- case T_Flonum:
- Printf (port, FLONUM_FORMAT, FLONUM(x)->val);
- break;
- case T_Boolean:
- Printf (port, "#%c", FIXNUM(x) ? 't' : 'f');
- break;
- case T_Void:
- break;
- case T_Unbound:
- Printf (port, "#[unbound]");
- break;
- case T_Special:
- Printf (port, "#[special]");
- break;
- case T_Character: {
- int c = CHAR(x);
- if (raw)
- Print_Char (port, c);
- else
- Pr_Char (port, c);
- break;
- }
- case T_Symbol:
- Pr_String (port, SYMBOL(x)->name, 1);
- break;
- case T_Pair:
- Pr_List (port, x, raw, depth, length);
- break;
- case T_Environment:
- Printf (port, "#[environment %u]", POINTER(x));
- break;
- case T_String:
- Pr_String (port, x, raw);
- break;
- case T_Vector:
- Pr_Vector (port, x, raw, depth, length);
- break;
- case T_Primitive:
- Printf (port, "#[primitive %s]", PRIM(x)->name);
- break;
- case T_Compound:
- if (Nullp (COMPOUND(x)->name)) {
- Printf (port, "#[compound %u]", POINTER(x));
- } else {
- Printf (port, "#[compound ");
- Print_Object (COMPOUND(x)->name, port, raw, depth, length);
- Print_Char (port, ']');
- }
- break;
- case T_Control_Point:
- Printf (port, "#[control-point %u]", POINTER(x));
- break;
- case T_Promise:
- Printf (port, "#[promise %u]", POINTER(x));
- break;
- case T_Port: {
- int str = PORT(x)->flags & P_STRING;
- char *p;
- switch (PORT(x)->flags & (P_INPUT|P_BIDIR)) {
- case 0: p = "output"; break;
- case P_INPUT: p = "input"; break;
- default: p = "input-output"; break;
- }
- Printf (port, "#[%s-%s-port ", str ? "string" : "file", p);
- if (str)
- Printf (port, "%u", POINTER(x));
- else
- Pr_String (port, PORT(x)->name, 0);
- Print_Char (port, ']');
- break;
- }
- case T_End_Of_File:
- Printf (port, "#[end-of-file]");
- break;
- case T_Autoload:
- Printf (port, "#[autoload ");
- Print_Object (AUTOLOAD(x)->files, port, raw, depth, length);
- Print_Char (port, ']');
- break;
- case T_Macro:
- if (Nullp (MACRO(x)->name)) {
- Printf (port, "#[macro %u]", POINTER(x));
- } else {
- Printf (port, "#[macro ");
- Print_Object (MACRO(x)->name, port, raw, depth, length);
- Print_Char (port, ']');
- }
- break;
- case T_Broken_Heart:
- Printf (port, "!!broken-heart!!");
- break;
- default:
- if (t < 0 || t >= MAX_TYPE || !Types[t].name)
- Panic ("bad type in print");
- (*Types[t].print)(x, port, raw, depth, length);
- }
- GC_Unlink;
- }
-
- Pr_Char (port, c) Object port; register c; {
- register char *p = 0;
-
- switch (c) {
- case ' ':
- p = "#\\space";
- break;
- case '\t':
- p = "#\\tab";
- break;
- case '\n':
- p = "#\\newline";
- break;
- case '\r':
- p = "#\\return";
- break;
- case '\f':
- p = "#\\formfeed";
- break;
- case '\b':
- p = "#\\backspace";
- break;
- default:
- if (c > ' ' && c < '\177')
- Printf (port, "#\\%c", c);
- else
- Printf (port, "#\\%03o", (unsigned char)c);
- }
- if (p) Printf (port, p);
- }
-
- Pr_List (port, list, raw, depth, length) Object port, list;
- register raw, depth, length; {
- Object tail;
- register len;
- register char *s = 0;
- GC_Node2;
-
- if (depth == 0) {
- Printf (port, "&");
- return;
- }
- GC_Link2 (port, list);
- if (!Nullp (list) && ((tail = Cdr (list)), TYPE(tail) == T_Pair)
- && ((tail = Cdr (tail)), Nullp (tail))) {
- tail = Car (list);
- if (EQ(tail, Sym_Quote))
- s = "'";
- else if (EQ(tail, Sym_Quasiquote))
- s = "`";
- else if (EQ(tail, Sym_Unquote))
- s = ",";
- else if (EQ(tail, Sym_Unquote_Splicing))
- s = ",@";
- if (s) {
- Printf (port, s);
- Print_Object (Car (Cdr (list)), port, raw,
- depth < 0 ? depth : depth-1, length);
- GC_Unlink;
- return;
- }
- }
- Print_Char (port, '(');
- for (len = 0; !Nullp (list); len++, list = tail) {
- if (length >= 0 && len >= length) {
- Printf (port, "...");
- break;
- }
- Print_Object (Car (list), port, raw, depth < 0 ? depth : depth-1,
- length);
- tail = Cdr (list);
- if (!Nullp (tail)) {
- if (TYPE(tail) == T_Pair)
- Print_Char (port, ' ');
- else {
- Printf (port, " . ");
- Print_Object (tail, port, raw, depth < 0 ? depth : depth-1,
- length);
- break;
- }
- }
- }
- Print_Char (port, ')');
- GC_Unlink;
- }
-
- Pr_Vector (port, vec, raw, depth, length) Object port, vec;
- register raw, depth, length; {
- register i, j;
- GC_Node2;
-
- if (depth == 0) {
- Printf (port, "&");
- return;
- }
- GC_Link2 (port, vec);
- Printf (port, "#(");
- for (i = 0, j = VECTOR(vec)->size; i < j; i++) {
- if (i) Print_Char (port, ' ');
- if (length >= 0 && i >= length) {
- Printf (port, "...");
- break;
- }
- Print_Object (VECTOR(vec)->data[i], port, raw,
- depth < 0 ? depth : depth-1, length);
- }
- Print_Char (port, ')');
- GC_Unlink;
- }
-
- Pr_String (port, str, raw) Object port, str; {
- register char *p = STRING(str)->data;
- register c, i, len = STRING(str)->size;
- GC_Node2;
-
- if (raw) {
- if (PORT(port)->flags & P_STRING) {
- Print_String (port, p, len);
- } else {
- if (fwrite (p, 1, len, PORT(port)->file) < len) {
- Saved_Errno = errno; /* errno valid here? */
- Primitive_Error ("write error on ~s: ~E", port);
- }
- }
- return;
- }
- GC_Link2 (port, str);
- Print_Char (port, '"');
- for (i = 0; i < STRING(str)->size; i++) {
- c = STRING(str)->data[i];
- if (c == '\\' || c == '"')
- Print_Char (port, '\\');
- if (c < ' ' || c >= '\177')
- Print_Special (port, c);
- else
- Print_Char (port, c);
- }
- Print_Char (port, '"');
- GC_Unlink;
- }
-
- Print_Special (port, c) Object port; register c; {
- register char *fmt = "\\%c";
-
- switch (c) {
- case '\b': c = 'b'; break;
- case '\t': c = 't'; break;
- case '\r': c = 'r'; break;
- case '\n': c = 'n'; break;
- default:
- fmt = "\\%03o";
- }
- Printf (port, fmt, (unsigned char)c);
- }
-
- Object P_Format (argc, argv) Object *argv; {
- Object port, str;
- register stringret = 0;
- GC_Node;
-
- port = argv[0];
- if (TYPE(port) == T_Boolean) {
- if (Truep (port)) {
- port = Curr_Output_Port;
- } else {
- stringret++;
- port = P_Open_Output_String ();
- }
- } else if (TYPE(port) == T_Port) {
- Check_Output_Port (port);
- } else Wrong_Type_Combination (port, "port or #t or #f");
- str = argv[1];
- Check_Type (str, T_String);
- GC_Link (port);
- Format (port, STRING(str)->data, STRING(str)->size, argc-2, argv+2);
- GC_Unlink;
- return stringret ? P_Get_Output_String (port) : Void;
- }
-
- Format (port, p, len, argc, argv) Object port; register char *p;
- register len; Object *argv; {
- register char *s, *ep;
- register c;
- char buf[256];
- extern sys_nerr;
- extern char *sys_errlist[];
- GC_Node;
-
- GC_Link (port);
- for (ep = p + len; p < ep; p++) {
- if (*p == '~') {
- if (++p == ep) break;
- if ((c = *p) == '~') {
- Print_Char (port, c);
- } else if (c == '%') {
- Print_Char (port, '\n');
- } else if (c == 'e' || c == 'E') {
- if (Saved_Errno > 0 && Saved_Errno < sys_nerr) {
- s = sys_errlist[Saved_Errno];
- sprintf (buf, "%c%s", isupper (*s) ? tolower (*s) :
- *s, s+1);
- } else {
- sprintf (buf, "error %d", Saved_Errno);
- }
- Print_Object (Make_String (buf, strlen (buf)), port,
- c == 'E', 0, 0);
- } else {
- if (--argc < 0)
- Primitive_Error ("too few arguments");
- if (c == 's' || c == 'a') {
- Print_Object (*argv, port, c == 'a', Print_Depth (),
- Print_Length ());
- argv++;
- } else if (c == 'c') {
- Check_Type (*argv, T_Character);
- Print_Char (port, CHAR(*argv));
- argv++;
- } else Print_Char (port, c);
- }
- } else {
- Print_Char (port, *p);
- }
- }
- GC_Unlink;
- }
-